<?php

/**
 * 
 * 单例模式被公认为是 反面模式，为了获得更好的可测试性和可维护性，请使用『依赖注入模式』
 * 数据库连接
 * 日志 (多种不同用途的日志也可能会成为多例模式)
 * 在应用中锁定文件 (系统中只存在一个 ...)
 * @author jiliangliang
 *
 */
trait  Singleton
{

    /**
     *
     * @var Singleton
     */
    private static $instance;

    /**
     * 通过懒加载获得实例（在第一次使用的时候创建）
     */
    public static function getInstance(...$args): self
    {
        var_dump($args);
        if (! isset(self::$instance)) {
            self::$instance = new static(...$args);
        }
        return self::$instance;
    }

    /**
     * 不允许从外部调用以防止创建多个实例
     * 要使用单例，必须通过 Singleton::getInstance() 方法获取实例
     */
    // private function __construct()
    // {}
    
    /**
     * 防止实例被克隆（这会创建实例的副本）
     */
    private function __clone()
    {}

    /**
     * 防止反序列化（这将创建它的副本）
     */
    private function __wakeup()
    {}
}

class Test
{
    use Singleton;

    public function printStr()
    {
        echo ("1");
    }
}

class Test2
{
    use Singleton;

    private $host;

    private $part;

    public function echo()
    {
        echo $this->host, $this->part;
    }

    function __construct($host, $part)
    {
        $this->part = $part;
        $this->host = $host;
    }
}
Test::getInstance()->printStr();
Test2::getInstance("aaaa", "bbbbb")->echo();

// 测试 ...$args
function test3(...$args): Test2
{
    return new Test2($args[0], $args[1]);
}

test3(1111, 33333)->echo();

